package com.qianniu.napi.admin.web;

import com.google.common.base.Strings;
import com.qianniu.napi.admin.entity.Jinfo;
import com.qianniu.napi.admin.entity.User;
import com.qianniu.napi.common.util.IdentifyingCode;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by chenxuebin on 2017/3/6.
 */
@Controller
public class AuthController {

    private static Logger logger = LoggerFactory.getLogger(AuthController.class);

    @RequestMapping("login")
    public String login(Model model, HttpServletRequest request) {
        setLogininfo(model, request);
        Subject currentUser = SecurityUtils.getSubject();
        if (currentUser.isAuthenticated() || currentUser.isRemembered()) {
            return "redirect:/home";
        }
        return "login";
    }

    @RequestMapping("/dologin")
    public String index(User user, Model model, HttpServletRequest req) {

        logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>/login GET come and method=" + req.getMethod().toUpperCase());
        setLogininfo(model, req);
        Subject currentUser = SecurityUtils.getSubject();
        if (currentUser.isAuthenticated() || currentUser.isRemembered()) {
            return "redirect:/home";
        }

        boolean rememberMe = WebUtils.isTrue(req, "rememberMe");
        String username = StringUtils.clean(req.getParameter("username"));
        String password = StringUtils.clean(req.getParameter("password"));
        String captcha = StringUtils.clean(req.getParameter("captcha"));

        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>captcha=" + captcha);

        if (Strings.isNullOrEmpty(username) || Strings.isNullOrEmpty(password)) {
            model.addAttribute("msg", "用户名密码不能为空");
            return "login";
        }
        if (Strings.isNullOrEmpty(captcha)) {
            model.addAttribute("msg", "验证码不能为空");
            return "login";
        }
        Session session = SecurityUtils.getSubject().getSession();
        String code = (String) session.getAttribute(IdentifyingCode.VERIFY_CODE_KEY);
        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>code=" + code);
        if (Strings.isNullOrEmpty(code) || !captcha.equals(code)) {
            model.addAttribute("msg", "验证码不正确");
            return "login";
        }
        String err = null;
        if (user.getUsername() != null && user.getPassword() != null) {
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword(), rememberMe);
            Subject subject = SecurityUtils.getSubject();
            try {
                subject.login(token);
                session.removeAttribute(IdentifyingCode.VERIFY_CODE_KEY);
                if (!subject.isAuthenticated()) {
                    err = "登陆验证失败";
                } else {
                    //验证是否登录成功
                    logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>subject.login OK");
                }
            } catch (UnknownAccountException e) {
                logger.info("对用户[" + user.getUsername() + "]进行登录验证..验证失败-username wasn't in the system");
                err = "登陆验证失败";
                logger.error(">>>login valid error", e);
            } catch (IncorrectCredentialsException ice) {
                logger.error("对用户[" + user.getUsername() + "]进行登录验证..验证失败-password didn't match", ice);
                err = "登陆验证失败";
            } catch (LockedAccountException lae) {
                logger.error("对用户[" + user.getUsername() + "]进行登录验证..验证失败-account is locked in the system", lae);
                err = "登陆验证失败";
            } catch (AuthenticationException ae) {
                logger.error(ae.getMessage());
                err = "登陆验证失败";
            } catch (Exception ae) {
                logger.error(ae.getMessage());
                err = "登陆验证失败";
            }
        }
        logger.info("========================================");
        logger.info("========================================");
        logger.info("========================================why login again err=" + err);
        if (!Strings.isNullOrEmpty(err)) {
            model.addAttribute("msg", err);
            return "login";
        } else {
            logger.info("==========login success");
            return "redirect:/home";
        }
    }

    /**
     * ajax登录请求
     *
     * @param username
     * @param password
     * @return
     */
    @RequestMapping(value = "ajaxLogin", method = RequestMethod.POST)
    @ResponseBody
    public Jinfo ajaxLogin(String username, String password, String captcha, Boolean rememberMe, Model model) {
        Jinfo info = new Jinfo();
        Map<String, Object> resultMap = new LinkedHashMap<String, Object>();
        logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>/ajaxLogin come");
        logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>username=" + username);
        logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>password=" + password);


        if (Strings.isNullOrEmpty(username) || Strings.isNullOrEmpty(password)) {
            info.setCode(4);
            info.setMsg("用户名密码不能为空！");
            return info;
        }
        if (captcha == null || captcha == "") {
            info.setCode(4);
            info.setMsg("验证码不能为空！");
            return info;
        }
        //转化成小写字母
        captcha = captcha.toLowerCase();
        Session session = SecurityUtils.getSubject().getSession();
        String code = (String) session.getAttribute(IdentifyingCode.VERIFY_CODE_KEY);

        //还可以读取一次后把验证码清空，这样每次登录都必须获取验证码
        //session.removeAttribute("_come");
        logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>captcha=" + captcha);
        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>code=" + code);

        if (Strings.isNullOrEmpty(code) || !captcha.equals(code)) {
            info.setCode(4);
            info.setMsg("验证码错误！");
            return info;
        }
        if (rememberMe == null) rememberMe = true;
        try {
            UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
            Subject subject = SecurityUtils.getSubject();
            subject.login(token);
            session.removeAttribute(IdentifyingCode.VERIFY_CODE_KEY);
            if (!subject.isAuthenticated()) {
                info.setCode(1);
                info.setMsg("用户密码错误");
            }
        } catch (Exception e) {
            logger.error("-------------------ajax login failed", e);
            info.setCode(5);
            info.setMsg(e.getMessage());
        }
        return info;
    }

    @RequestMapping("/regist")
    public String regist(User user) {

        //生成盐（部分，需要存入数据库中）
        String random = new SecureRandomNumberGenerator().nextBytes().toHex();
        //将原始密码加盐（上面生成的盐），并且用md5算法加密三次，将最后结果存入数据库中
        String result = new Md5Hash("password", random, 2).toString();


        return "login";
    }

    /**
     * 对密码进行md5加密,并返回密文和salt，包含在User对象中
     *
     * @param username 用户名
     * @param password 密码
     * @return 密文和salt
     */
    public static User md5Password(String username, String password, String salt) {

//        SecureRandomNumberGenerator secureRandomNumberGenerator=new SecureRandomNumberGenerator();
//        String salt= secureRandomNumberGenerator.nextBytes().toHex();

        //组合username,两次迭代，对密码进行加密
        String password_cipherText = new Md5Hash(password, username + salt, 2).toBase64();
        User user = new User();
        user.setPassword(password_cipherText);
//        user.setSalt(salt);
        user.setUsername(username);
        return user;
    }

    /**
     * @Title: img
     * @Description: 图形验证码
     * @since V1.0.0
     */
    @RequestMapping("/validcode")
    public void img(HttpServletRequest request, HttpServletResponse response) {

        response.setContentType("image/jpeg");
        response.setHeader("pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Cache-Control", "no-store");
        response.setDateHeader("Expires", -1);
        HttpSession session = request.getSession();
        BufferedImage image = null;
        IdentifyingCode ic = new IdentifyingCode();
        List lst = ic.drawIdentifyingCode();
        image = (BufferedImage) lst.get(0);
        String code = lst.get(1).toString();
        session.removeAttribute(IdentifyingCode.VERIFY_CODE_KEY);
        session.setAttribute(IdentifyingCode.VERIFY_CODE_KEY, code);

//        TokenManager.setVal2Session(VerifyCodeUtils.V_CODE, captcha.text().toLowerCase());
        if (null == image) {
            logger.error("validcode error for IdentifyingCode drawIdentifyingCode null");
            return;
            // 输出图象到页面
            /*JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(response.getOutputStream());
            encoder.encode(image);*/
        }
        try {
            ImageIO.write(image, "jpg", response.getOutputStream());
            response.getOutputStream().close();
        } catch (Exception e) {
            logger.error("validcode error", e);
        }
    }

    /**
     * @Title: img
     * @Description: 图形验证码
     * @since V1.0.0
     */

//    @RequestMapping("/validcode")
//    public void img(HttpServletResponse res) {
//        CaptchaRender img = new CaptchaRender(DEFAULT_CAPTCHA_LEN);
//        Session s = SecurityUtils.getSubject().getSession();
//        s.setAttribute(CaptchaRender.DEFAULT_CAPTCHA_MD5_CODE_KEY, img.getMd5RandonCode());
//        BufferedImage image = new BufferedImage(img.imgWidth, img.imgHeight, BufferedImage.TYPE_INT_RGB);
//        img.drawGraphic(image);
//
//        res.setHeader("Pragma", "no-cache");
//        res.setHeader("Cache-Control", "no-cache");
//        res.setDateHeader("Expires", 0);
//        res.setContentType("image/jpeg");
//        ServletOutputStream sos = null;
//        try {
//            sos = res.getOutputStream();
//            ImageIO.write(image, "jpeg", sos);
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        } finally {
//            if (sos != null)
//                try {
//                    sos.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//        }
//    }

    /**
     * 本地登出页面
     *
     * @param redirectAttributes
     * @return
     */
    @RequestMapping(value = "/logout")
    public String logout(RedirectAttributes redirectAttributes,
                         Model model, HttpServletRequest request) {
        System.out.println("encodePassword=");

        //使用权限管理工具进行用户的退出，跳出登录，给出提示信息
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            subject.logout();
        }
        setLogininfo(model, request);
        return "login";
    }

    private void setLogininfo(Model model, HttpServletRequest request) {

        logger.info(">>>request.getServerName()=" + request.getServerName());
        String bgurl = "https://img.niucaiduo.com/logo/bg-oa.jpg";
        if (request.getServerName().toLowerCase().startsWith("fmall")) {
            logger.info(">>>setLogininfo to fmall");
            model.addAttribute("jtitle", "LCFL");
            model.addAttribute("bgurl", bgurl);
            model.addAttribute("title", "欢迎使用理财返利后台管理系统");
        } else if (request.getServerName().toLowerCase().indexOf("huakou") >= 0) {
            logger.info(">>>setLogininfo to taozi");
            model.addAttribute("jtitle", "TZ");
            model.addAttribute("bgurl", "https://img.niucaiduo.com/logo/kanya.jpg");
            model.addAttribute("title", "欢迎使用华口云后台管理系统");
        } else if (request.getServerName().toLowerCase().startsWith("vms")) {
            logger.info(">>>setLogininfo to taozi");
            model.addAttribute("jtitle", "TZ");
            model.addAttribute("bgurl", bgurl);
            model.addAttribute("title", "欢迎使用桃子股票分析系统");
        } else {
            logger.info(">>>setLogininfo to qianniu");
            model.addAttribute("jtitle", "OPEN");
            model.addAttribute("bgurl", bgurl);
            model.addAttribute("title", "欢迎使用小程序后台管理系统");
        }
    }

    public static void main(String[] args) {

        String pwd = new Md5Hash("qn654321", "admin", 3).toString();
        System.out.println(pwd);

    }

}
